package com.learn.test.spi;

import com.learn.test.spi.beans.SpiInterface;

import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.ServiceLoader;

/**
 * SPI全称Service Provider Interface，即服务发现机制。
 * -    约定在ClassPath下的META-INF/services文件夹查找文件，自动加载文件中定义的类。文件名为接口全路径，文件内容为接口实现类全路径（一行一个）
 * -    普通反射的类全路径需要在代码中写死，非常不灵活，不易扩展，所以出现SPI
 * <p>
 * 实际SPI没学完，参考以前的CSDN笔记
 * https://blog.csdn.net/weixin_51699336/article/details/123741912
 * https://blog.csdn.net/weixin_51699336/article/details/123742089
 */
public class SpiMain {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 1️⃣准备工作，编写接口SpiInterface与实现类SpiInterfaceImpl1、SpiInterfaceImpl2、SpiInterfaceImpl3
        
        // 2️⃣resource下创建约定目录META-INF/services，以及约定命名和内容的文件名和文件内容
        
        // 3️⃣SPI机制实现的两种方式
        //  方式一：sun.misc.Service包下的Service.provider，但是Service不直接给外部使用，推荐方式二
        /*Iterator<SpiInterface> providers = Service.providers(SpiInterface.class);
        while (providers.hasNext()) {
            SpiInterface spi = providers.next();
            spi.sayHello();
        }*/
        
        //  方式二：java.util.ServiceLoader包下的ServiceLoader.load
        ServiceLoader<SpiInterface> loader = ServiceLoader.load(SpiInterface.class);
        Iterator<SpiInterface> iterator = loader.iterator();
        while (iterator.hasNext()) {
            SpiInterface spi = iterator.next();
            spi.sayHello();
        }
        
        // 以上是实现SPI的方式，mysql的Driver实际上有用到SPI，我们看看这部分代码
        //  先导包，编写测试类SpiMysqlMain
    }
}
